package commons.utils;

import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PartInitException;

import commons.utils.facades.DialogConstantsFacade;
import commons.utils.facades.GCFacade;
import commons.utils.facades.SWTFacade;

/**
 * Miscellaneous UI utilities.
 */
public class UIUtils {

    /**
     * Number of horizontal dialog units per character, value <code>4</code>.
     */
    private static final int HORIZONTAL_DIALOG_UNIT_PER_CHAR = 4;

    /**
     * Number of vertical dialog units per character, value <code>8</code>.
     */
    private static final int VERTICAL_DIALOG_UNITS_PER_CHAR = 8;

    static private int _dialogHorizontalSpacing;
    static private int _dialogMarginHeight;
    static private int _dialogMarginWidth;
    static private int _dialogVerticalSpacing;
    static private int _averageTextCharacterWidth = -1;
    static private int _averageTextLetterWidth = -1;
    static private int _averageTextDigitWidth = -1;
    static private int _wideTextCharacterWidth = -1;
    static private int _widestTextLetterWidth = -1;
    static private int _widestTextDigitWidth = -1;
    static private int _standardButtonWidth;
    static private int _averageHeight;
    static private int _averageWidth;
    static {
	initFontStatistics();
    }

    static private void initFontStatistics() {
	Shell shell = new Shell();
	Label label = new Label(shell, SWT.NONE);
	Font standardFont = label.getFont();
	GC gc = new GC(Display.getCurrent());
	gc.setFont(standardFont);
	FontMetrics fontMetrics = gc.getFontMetrics();

	int totalDLUPixels = fontMetrics.getAverageCharWidth() * 50;
	_standardButtonWidth = totalDLUPixels / 4;
	if (_standardButtonWidth * 4 < totalDLUPixels)
	    _standardButtonWidth++;

	int totalWidth = 0;
	int count = 0;
	int letterCount = 0;
	int totalLetterWidth = 0;
	int digitCount = 0;
	int totalDigitWidth = 0;
	for (char c = 0; c < 255; c++) {
	    if (Character.isDefined(c)) {
		int advanceWidth = GCFacade.getDefault().getAdvanceWidth(gc, c);
		if (_wideTextCharacterWidth < advanceWidth)
		    _wideTextCharacterWidth = advanceWidth;
		totalWidth += advanceWidth;
		count++;
		if (Character.isLetter(c)) {
		    if (_widestTextLetterWidth < advanceWidth)
			_widestTextLetterWidth = advanceWidth;
		    totalLetterWidth += advanceWidth;
		    letterCount++;
		}

		if (Character.isDigit(c)) {
		    if (_widestTextDigitWidth < advanceWidth)
			_widestTextDigitWidth = advanceWidth;
		    totalDigitWidth += advanceWidth;
		    digitCount++;
		}
	    }
	}

	_averageTextCharacterWidth = totalWidth / count;
	if (_averageTextCharacterWidth * count < totalWidth)
	    _averageTextCharacterWidth++;

	_averageTextLetterWidth = totalLetterWidth / letterCount;
	if (_averageTextLetterWidth * letterCount < totalLetterWidth)
	    _averageTextLetterWidth++;

	_averageTextDigitWidth = totalDigitWidth / digitCount;
	if (_averageTextDigitWidth * digitCount < totalDigitWidth)
	    _averageTextDigitWidth++;

	_averageHeight = fontMetrics.getHeight();
	_averageWidth = fontMetrics.getAverageCharWidth();

	_dialogMarginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
	_dialogMarginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
	_dialogVerticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
	_dialogHorizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);

	gc.dispose();
	label.dispose();
	shell.dispose();
    }

    public static int convertVerticalDLUsToPixels(int count) {
	return (_averageHeight * count + VERTICAL_DIALOG_UNITS_PER_CHAR / 2) / VERTICAL_DIALOG_UNITS_PER_CHAR;
    }

    public static int convertHorizontalDLUsToPixels(int count) {
	return (_averageWidth * count + HORIZONTAL_DIALOG_UNIT_PER_CHAR / 2) / HORIZONTAL_DIALOG_UNIT_PER_CHAR;
    }

    /**
     * Returns true of the given control or any of it's children has the focus.
     */
    public static boolean isFocusAncestor(Control control) {
	Display display = control.getDisplay();
	Control focusControl = display.getFocusControl();
	while (focusControl != null) {
	    if (focusControl == control)
		return true;
	    focusControl = focusControl.getParent();
	}
	return false;
    }

    /**
     * A convenience method for running editor init tasks
     */
    public static void runPartInit(final ISafeRunnable runnable) throws PartInitException {
	final PartInitException[] x = new PartInitException[1];
	SafeRunner.run(new ISafeRunnable() {
	    @Override
	    public void run() throws Exception {
		runnable.run();
	    }

	    @Override
	    public void handleException(Throwable e) {
		// Logger.error(e);
		runnable.handleException(e);
		if ((e instanceof PartInitException) == false) {
		    Status status = new Status(Status.ERROR, "", 0, e.getMessage(), e);
		    e = new PartInitException(status);
		}
		x[0] = (PartInitException) e;
	    }
	});
	if (x[0] != null) {
	    throw x[0];
	}
    }

    /**
     * Resizes all the columns in a table to fit the column's contents,
     * including the column header.
     * 
     * WARNING: Do not call this method from within a table resize event. This
     * method may cause the table to resize, therefore calling this method from
     * within a table resize event may cause a stack overflow.
     */
    static public void packTableColumns(Table table) {
	table.setRedraw(false);
	TableColumn[] columns = table.getColumns();
	int columnWidth = 0;
	for (int i = 0; i < columns.length; i++) {
	    TableColumn column = columns[i];
	    int minWidth = column.getWidth();
	    if (minWidth > 0) {
		column.pack();
	    }
	    if ((column.getWidth() < minWidth) && (i < columns.length - 1)) {
		column.setWidth(minWidth);
	    }
	    if (i < columns.length - 1) {
		columnWidth += column.getWidth();
	    }
	}
	table.setRedraw(true);
    }

    /**
     * Resizes all the columns in a tree to fit the column's contents, including
     * the column header.
     * 
     * WARNING: Do not call this method from within a tree resize event. This
     * method may cause the tree to resize, therefore calling this method from
     * within a tree resize event may cause a stack overflow.
     */
    static public void packTreeColumns(Tree tree) {
	tree.setRedraw(false);
	TreeColumn[] columns = tree.getColumns();
	int columnWidth = 0;
	for (int i = 0; i < columns.length; i++) {
	    TreeColumn column = columns[i];
	    int minWidth = column.getWidth();
	    if (minWidth > 0) {
		column.pack();
	    }
	    if ((column.getWidth() < minWidth) && (i < columns.length - 1)) {
		column.setWidth(minWidth);
	    } else if (SWTFacade.isRAP() && i == 0) {
		// TODO [agk] - remove additional column with when RAP fixed
		column.setWidth(column.getWidth() + 100);
	    }
	    if (i < columns.length - 1) {
		columnWidth += column.getWidth();
	    }
	}
	tree.setRedraw(true);
    }

    static public void packTableColumns(Table table, int row) {
	table.setRedraw(false);
	TableColumn[] columns = table.getColumns();
	int columnWidth = 0;
	for (int i = 0; i < columns.length; i++) {
	    TableColumn column = columns[i];
	    int minWidth = column.getWidth();
	    column.pack();
	    if (column.getWidth() < minWidth)
		column.setWidth(minWidth);
	    if (i < columns.length - 1)
		columnWidth += column.getWidth();
	}
	table.setRedraw(true);
    }

    /**
     * Evenly expands column widths to suck up any leftover space in the table.
     * Does not expand a column past it's packed width.
     * 
     * This method should only be called on hidden tables since it will cause
     * crazy insane flicker otherwise.
     */
    static public void evenlyWidenTableColumns(Table table) {
	table.setRedraw(false);
	TableColumn[] columns = table.getColumns();
	if (0 < columns.length) {
	    int clientWidth = table.getClientArea().width;
	    clientWidth -= table.getBorderWidth() * 2;

	    int totStartWidth = 0;
	    int[] startWidths = new int[columns.length];
	    for (int i = 0; i < columns.length; i++) {
		TableColumn column = columns[i];
		totStartWidth += startWidths[i] = column.getWidth();
		column.pack();
	    }

	    if (clientWidth <= totStartWidth) {
		return;
	    }
	    int[] packedWidths = new int[columns.length];
	    int totPackedWidth = 0;
	    for (int i = 0; i < columns.length; i++) {
		TableColumn column = columns[i];
		int width = column.getWidth();
		if (width < startWidths[i])
		    column.setWidth(width = startWidths[i]);
		totPackedWidth += packedWidths[i] = width;
	    }

	    if (totPackedWidth < clientWidth) {
		autosizeLastColumnInTable(table);
		return;
	    }

	    int totExcess = totPackedWidth - clientWidth;
	    int totDiff = totPackedWidth - totStartWidth;
	    int totFinalWidth = 0;
	    for (int i = 0; i < columns.length; i++) {
		TableColumn column = columns[i];
		int packedWidth = packedWidths[i];
		int diff = packedWidth - startWidths[i];
		int excess = (totExcess * diff) / totDiff;
		if (0 < excess) {
		    int w = packedWidth - excess;
		    totFinalWidth += w;
		    column.setWidth(w);
		}
	    }
	    // Logger.debug("clientWidth=" + clientWidth +
	    // ", total final width=" + totFinalWidth);
	}
	table.setRedraw(true);
    }

    /**
     * Expands the last column in a table to suck up any left over space in it's
     * table.
     */
    static public void autosizeLastColumnInTable(Table table) {
	autosizeColumnInTable(table, table.getColumns().length - 1);
    }

    /**
     * Expands the last column in a tree to suck up any left over space.
     */
    static public void autosizeLastColumnInTree(Tree tree) {
	autosizeColumnInTree(tree, tree.getColumns().length - 1);
    }

    /**
     * Expands the last column in a table to suck up any left over space in it's
     * table.
     */
    static public void autosizeColumnInTable(Table table, int columnIndex) {
	table.setRedraw(false);
	TableColumn[] columns = table.getColumns();
	if (0 < columns.length) {
	    int totColumnWidth = 0;
	    for (int i = 0; i < columns.length; i++)
		if (i != columnIndex)
		    totColumnWidth += columns[i].getWidth();

	    int clientWidth = table.getClientArea().width;
	    clientWidth -= table.getBorderWidth() * 2;
	    int lastColWidth = clientWidth - totColumnWidth;
	    TableColumn lastColumn = columns[columnIndex];
	    if (lastColumn.getWidth() < lastColWidth)
		lastColumn.setWidth(lastColWidth);
	}
	table.setRedraw(true);
    }

    /**
     * Expands the last column in a table to suck up any left over space in it's
     * table.
     */
    static public void autosizeColumnInTree(Tree tree, int columnIndex) {
	tree.setRedraw(false);
	TreeColumn[] columns = tree.getColumns();
	if (0 < columns.length) {
	    int totColumnWidth = 0;
	    for (int i = 0; i < columns.length; i++)
		if (i != columnIndex)
		    totColumnWidth += columns[i].getWidth();

	    int clientWidth = tree.getClientArea().width;
	    clientWidth -= tree.getBorderWidth() * 2;
	    int lastColWidth = clientWidth - totColumnWidth;
	    TreeColumn lastColumn = columns[columnIndex];
	    if (lastColumn.getWidth() < lastColWidth)
		lastColumn.setWidth(lastColWidth);
	}
	tree.setRedraw(true);
    }

    /**
     * Centers a shell on it's Display
     */
    static public void center(Shell shell) {
	Display display = shell.getDisplay();
	Rectangle bounds = display.getBounds();
	Rectangle rect = shell.getBounds();
	int x = bounds.x + (bounds.width - rect.width) / 2;
	int y = bounds.y + (bounds.height - rect.height) / 3;
	shell.setLocation(x, y);
    }

    /**
     * Looks for all input elements (text fields, checkboxes, etc) and disables
     * them. Recurses through all children.
     */
    public static void setReadOnlyOnAllInputElements(Widget parent, boolean value) {
	if (isInputElement(parent))
	    setEnabled(parent, value);
	if (parent instanceof Composite) {
	    Control[] children = ((Composite) parent).getChildren();
	    for (int i = 0; i < children.length; i++) {
		setReadOnlyOnAllInputElements(children[i], value);
	    }
	}
    }

    private static boolean isInputElement(Widget widget) {
	if (widget instanceof Text)
	    return true;
	if (widget instanceof Combo)
	    return true;
	if (widget instanceof Button)
	    return true;
	if (widget instanceof Menu)
	    return true;
	return false;
    }

    private static void setEnabled(Widget widget, boolean value) {
	if (widget instanceof Control)
	    ((Control) widget).setEnabled(value);
	if (widget instanceof Menu)
	    ((Menu) widget).setEnabled(value);
    }

    public static final boolean isDescendant(Composite parent, Control target) {
	if (parent == target)
	    return true;
	Control[] children = parent.getChildren();
	for (int i = 0; i < children.length; i++) {
	    Control child = children[i];
	    if (target == child)
		return true;
	    if (child instanceof Composite) {
		if (isDescendant((Composite) child, target))
		    return true;
	    }
	}
	return false;
    }

    public static void showErrorMessage(final Control tabPage, final String message) {
	showErrorMessage(tabPage, "Error Message", message);
    }

    public static void showErrorMessage(final Control tabPage, final String title, final String message) {
	if (tabPage.isDisposed()) {
	    showErrorMessage(message);
	    return;
	}

	tabPage.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		Shell shell = tabPage.getShell();
		MessageDialog.openError(shell, title, message);
	    }
	});
    }

    public static void showErrorMessage(final String message) {
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openError(Display.getDefault().getActiveShell(), "Error Message", message);
	    }
	});
    }

    public static boolean showErrorMessageWithToggle(final String message, final String toggleMessage, final boolean toggleState) {
	final boolean[] toggle = { toggleState };
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		toggle[0] = MessageDialogWithToggle.openError(Display.getDefault().getActiveShell(), "Error Message", message,
			toggleMessage, toggleState, null, null).getToggleState();
	    }
	});
	return toggle[0];
    }

    public static void showWarningMessage(final String message) {
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openWarning(Display.getDefault().getActiveShell(), "Warning Message", message);
	    }
	});
    }

    public static boolean showWarningMessageWithToggle(final String message, final String toggleMessage,
	    final boolean toggleState) {
	final boolean[] toggle = { toggleState };
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		toggle[0] = MessageDialogWithToggle.openWarning(Display.getDefault().getActiveShell(), "Warning Message",
			message, toggleMessage, toggleState, null, null).getToggleState();
	    }
	});
	return toggle[0];
    }

    public static boolean showWarningMessageWithToggle(final String title, final String message, final String toggleMessage,
	    final boolean toggleState) {
	final boolean[] toggle = { toggleState };
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		toggle[0] = MessageDialogWithToggle.openWarning(Display.getDefault().getActiveShell(), title, message,
			toggleMessage, toggleState, null, null).getToggleState();
	    }
	});
	return toggle[0];
    }

    public static void showWarningMessageWithHyperlink(final String[] message, final String[] hyperlink) {
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		commons.ui.dialog.MessageDialogWithHyperlink.openWarning(Display.getDefault().getActiveShell(),
			"Warning Message", message, hyperlink);
	    }
	});
    }

    public static void showWarningMessage(final Composite tabPage, final String message) {
	if (tabPage.isDisposed()) {
	    showWarningMessage(message);
	    return;
	}

	tabPage.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openWarning(tabPage.getShell(), "Warning Message", message);
	    }
	});
    }

    public static void showInfoMessage(final String title, final String message) {
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openInformation(Display.getDefault().getActiveShell(), title, message);
	    }
	});
    }

    public static void showMessage(final String title, final String message) {
	Display.getDefault().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openWarning(Display.getDefault().getActiveShell(), title, message);
	    }
	});
    }

    public static void showMessage(final Composite tabPage, final String title, final String message) {
	tabPage.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		MessageDialog.openWarning(tabPage.getShell(), title, message);
	    }
	});
    }

    public static int showQuestionWithCancel(Composite tabPage, String message) {
	return showQuestionWithCancel(tabPage.getShell(), message);
    }

    public static int showQuestionWithCancel(String message) {
	return showQuestionWithCancel(Display.getDefault().getActiveShell(), message);
    }

    public static int showQuestionWithCancel(Shell shell, String message) {
	final MessageDialog dialog = new MessageDialog(shell, "Do you wish to proceed?", null, message, MessageDialog.QUESTION,
		new String[] { DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getNoLabel(),
			DialogConstantsFacade.getCancelLabel() }, 0);
	shell.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		dialog.open();
	    }
	});
	int result = dialog.getReturnCode();
	if (result == 0) {
	    return IDialogConstants.YES_ID;
	}
	if (result == 1) {
	    return IDialogConstants.NO_ID;
	}
	return IDialogConstants.CANCEL_ID;
    }

    public static boolean showQuestion(Composite tabPage, String message) {
	return MessageDialog.openQuestion(tabPage.getShell(), "Do you wish to proceed?", message);
    }

    public static boolean showQuestion(String message) {
	return showQuestion("Do you wish to proceed?", message);
    }

    public static boolean showQuestion(String title, String message) {
	return MessageDialog.openQuestion(Display.getDefault().getActiveShell(), title, message);
    }

    public static int showQuestionWithYesAllCancel(String message) {
	return showQuestionWithYesAllCancel("Do you wish to proceed?", message);
    }

    public static int showQuestionWithYesAllCancel(String title, String message) {
	Shell shell = Display.getDefault().getActiveShell();
	final MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.QUESTION, new String[] {
		DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getNoLabel(),
		DialogConstantsFacade.getCancelLabel() }, 0);
	shell.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		dialog.open();
	    }
	});
	int result = dialog.getReturnCode();
	if (result == 0) {
	    return IDialogConstants.YES_ID;
	}
	if (result == 1) {
	    return IDialogConstants.YES_TO_ALL_ID;
	}
	if (result == 2) {
	    return IDialogConstants.NO_ID;
	}
	return IDialogConstants.CANCEL_ID;
    }

    public static int showQuestionWithNoAll(String message) {
	return showQuestionWithNoAll("Do you wish to proceed?", message);
    }

    public static int showQuestionWithNoAll(String title, String message) {
	Shell shell = Display.getDefault().getActiveShell();
	final MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.QUESTION, new String[] {
		DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getNoLabel(),
		DialogConstantsFacade.getNoToAllLabel(), DialogConstantsFacade.getCancelLabel() }, 0);
	shell.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		dialog.open();
	    }
	});
	int result = dialog.getReturnCode();
	if (result == 0) {
	    return IDialogConstants.YES_ID;
	}
	if (result == 1) {
	    return IDialogConstants.NO_ID;
	}
	if (result == 2) {
	    return IDialogConstants.NO_TO_ALL_ID;
	}
	return IDialogConstants.CANCEL_ID;
    }

    public static int showQuestionWithYesNoAll(String title, String message) {
	Shell shell = Display.getDefault().getActiveShell();
	final MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.QUESTION, new String[] {
		DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getNoLabel(),
		DialogConstantsFacade.getYesToAllLabel(), DialogConstantsFacade.getNoToAllLabel() }, 0);
	shell.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		dialog.open();
	    }
	});
	int result = dialog.getReturnCode();
	if (result == 0) {
	    return IDialogConstants.YES_ID;
	}
	if (result == 1) {
	    return IDialogConstants.NO_ID;
	}
	if (result == 2) {
	    return IDialogConstants.YES_TO_ALL_ID;
	}
	return IDialogConstants.NO_TO_ALL_ID;
    }

    public static int showQuestionWithYesNoAllCancel(String title, String message) {
	Shell shell = Display.getDefault().getActiveShell();
	final MessageDialog dialog = new MessageDialog(shell, title, null, message, MessageDialog.QUESTION, new String[] {
		DialogConstantsFacade.getYesLabel(), DialogConstantsFacade.getNoLabel(),
		DialogConstantsFacade.getYesToAllLabel(), DialogConstantsFacade.getNoToAllLabel(),
		DialogConstantsFacade.getCancelLabel() }, 0);
	shell.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		dialog.open();
	    }
	});
	int result = dialog.getReturnCode();
	if (result == 0) {
	    return IDialogConstants.YES_ID;
	}
	if (result == 1) {
	    return IDialogConstants.NO_ID;
	}
	if (result == 2) {
	    return IDialogConstants.YES_TO_ALL_ID;
	}
	if (result == 3) {
	    return IDialogConstants.NO_TO_ALL_ID;
	}
	return IDialogConstants.CANCEL_ID;
    }

    public static void showInfoMessage(Composite tabPage, String message) {
	showInfoMessage(tabPage, "", message);
    }

    public static void showInfoMessage(final Composite tabPage, final String title, final String message) {
	if (tabPage.isDisposed()) {
	    showInfoMessage(title, message);
	    return;
	}

	tabPage.getDisplay().syncExec(new Runnable() {
	    @Override
	    public void run() {
		Shell shell = tabPage.getShell();
		MessageDialog.openInformation(shell, title, message);
	    }
	});
    }

    /**
     * Positions the pulldown control underneath the bottom lefthand corner of
     * the chiclet control. However, the pulldown control position will be
     * adjusted so that no part of it is off the display.
     * 
     * @param newShell
     * @param control
     */
    public static void positionPulldown(Control pulldown, Control chiclet) {
	Point p = chiclet.getLocation();
	p.y += chiclet.getSize().y;
	pulldown.setLocation(p);
    }

    static public int getDialogHorizontalSpacing() {
	return _dialogHorizontalSpacing;
    }

    static public int getDialogMarginHeight() {
	return _dialogMarginHeight;
    }

    static public int getDialogMarginWidth() {
	return _dialogMarginWidth;
    }

    static public int getDialogVerticalSpacing() {
	return _dialogVerticalSpacing;
    }

    static public int getAverageTextCharacterAdvance() {
	return _averageTextCharacterWidth;
    }

    static public int getWidestTextCharacterAdvance() {
	return _wideTextCharacterWidth;
    }

    static public int getAverageTextLetterAdvance() {
	return _averageTextLetterWidth;
    }

    static public int getWidestTextLetterAdvance() {
	return _widestTextLetterWidth;
    }

    static public int getAverageTextDigitAdvance() {
	return _averageTextDigitWidth;
    }

    static public int getWidestTextDigitAdvance() {
	return _widestTextDigitWidth;
    }

    static public int getStandardButtonWidth() {
	return _standardButtonWidth;
    }

    public static GridLayout setDialogSpacing(GridLayout pLayout) {
	pLayout.horizontalSpacing = getDialogHorizontalSpacing();
	pLayout.verticalSpacing = getDialogVerticalSpacing();
	pLayout.marginHeight = getDialogMarginHeight();
	pLayout.marginWidth = getDialogMarginWidth();
	return pLayout;
    }

}
